package com.study.manage.mvc.common;

import java.io.IOException;
import java.io.OutputStreamWriter;
import java.text.SimpleDateFormat;
import java.util.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.ParseException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.ModelAttribute;

import com.google.common.collect.Lists;
import com.qiniu.util.Auth;
import com.study.manage.dal.SmsBatchRepository;
import com.study.manage.dal.UserSmsRepository;
import com.study.manage.domain.SmsBatch;
import com.study.manage.domain.UserSms;
import com.study.manage.domain.enumm.JpushTarget;
import com.study.manage.domain.enumm.UserSmsState;
import com.study.manage.domain.enumm.UserSmsType;
import com.study.manage.dto.BaseProperties;
import com.study.manage.dto.SessionUser;
import com.study.manage.utils.CmnStringUtils;
import com.study.manage.utils.Digests;
import com.study.manage.utils.Encodes;
import com.study.manage.utils.JsonMapper;
import com.study.manage.utils.ManageUtils;

import cn.jpush.api.JPushClient;
import cn.jpush.api.push.model.Options;
import cn.jpush.api.push.model.Platform;
import cn.jpush.api.push.model.PushPayload;
import cn.jpush.api.push.model.audience.Audience;
import cn.jpush.api.push.model.audience.AudienceTarget;
import cn.jpush.api.push.model.notification.AndroidNotification;
import cn.jpush.api.push.model.notification.IosNotification;
import cn.jpush.api.push.model.notification.Notification;

/**
 * Controller服务处理基类
 *
 */
@Scope("prototype")
public class BaseController extends BaseProperties {

    protected Logger logger = LoggerFactory.getLogger(this.getClass());

    protected JsonMapper jsonMapper = new JsonMapper();

    protected HttpServletRequest request;
    protected HttpServletResponse response;
    protected HttpSession session;

    @Autowired
    private UserSmsRepository userSmsRepository;
    @Autowired
    private SmsBatchRepository smsBatchRepository;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    public void cleanRedisData(String key) {
        try {
            Set<String> keys = this.stringRedisTemplate.keys(key);
            this.stringRedisTemplate.delete(keys);
        } catch (Exception e) {
            logger.error("", e);
        }
    }

    protected static final String PASS_CODE_NAME = "PASS_CODE_NAME";
    protected static final String PAY_CODE_NAME = "PAY_CODE_NAME";
    protected static final String CODE_NAME = "CODE";

    protected String getUpToken() {
        Auth auth = Auth.create(ak, sk);
        return auth.uploadToken(zone);
    }

    protected String getUpToken(String key) {
        Auth auth = Auth.create(ak, sk);
        return auth.uploadToken(zone, key);
    }

    protected String getIpAddr(HttpServletRequest request) {
        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return ip;
    }

    protected static String hashPassword(String password, String scret, String token) {
        return Encodes.encodeBase64(
                Digests.sha1(new StringBuilder(password).append(scret).append(token).toString()));
    }

    @ModelAttribute
    public void setReqAndRes(HttpServletRequest request, HttpServletResponse response) {

        this.request = request;
        this.response = response;
        this.session = request.getSession();
    }

    protected void logout(HttpServletRequest request) {
        request.getSession().removeAttribute("user");
    }

    public SessionUser getUserInfo() {
        return (SessionUser) request.getSession().getAttribute("user");
    }

    public Map<String, Object> getRequestParameter(HttpServletRequest request) {
        Map<String, Object> map = new HashMap<String, Object>();
        Enumeration<String> en = request.getParameterNames();
        while (en.hasMoreElements()) {
            String key = (String) en.nextElement();
            String value = request.getParameter(key);
            map.put(key, value);
        }
        return map;
    }

    @SuppressWarnings({"unchecked", "rawtypes"})
    public Object getRequestParameter(HttpServletRequest request, Class c) {
        Map<String, Object> map = new HashMap<String, Object>();
        Enumeration<String> en = request.getParameterNames();
        while (en.hasMoreElements()) {
            String key = (String) en.nextElement();
            String value = request.getParameter(key);
            map.put(key, value);
        }
        return jsonMapper.fromJson(jsonMapper.toJson(map), c);
    }

    public void sendPhoneCode(String string, String phone) throws ParseException, IOException {

        String code = ManageUtils.getRandomNum(6);
        UserSms sms = new UserSms();
        sms.code = code;
        sms.phone = phone;
        // 修改密码
        if (CmnStringUtils.equals("PASS_CODE_NAME", string)) {
            request.getSession().setAttribute(PASS_CODE_NAME, code);
            sms.type = UserSmsType.FORGOTTEN;
        }
        // 支付
        if (CmnStringUtils.equals("PAY_CODE_NAME", string)) {
            request.getSession().setAttribute(PAY_CODE_NAME, code);
            sms.type = UserSmsType.PAYCONF;
        }
        // 认证
        if (CmnStringUtils.equals("CODE_NAME", string)) {
            request.getSession().setAttribute(CODE_NAME, code);
            sms.type = UserSmsType.ORGANIZA_RZ;
        }
        CloseableHttpClient httpclient = HttpClients.createDefault();
        HttpPost httpPost = new HttpPost(smsSendUrl);
        List<NameValuePair> nvps = Lists.newArrayList();
        nvps.add(new BasicNameValuePair("apikey", smsApiKey));
        nvps.add(new BasicNameValuePair("mobile", phone));
        nvps.add(new BasicNameValuePair("text", smsRegText.replace("#code#", code)));
        httpPost.setEntity(new UrlEncodedFormEntity(nvps, "UTF-8"));
        CloseableHttpResponse response = httpclient.execute(httpPost);
        try {
            String json = EntityUtils.toString(response.getEntity());
            sms.response = json;
            Map<String, Object> map = jsonMapper.fromJson(json, Map.class);
            if (json.startsWith("{\"code\":0")) {
                sms.state = UserSmsState.SUCCESS;
            } else {
                sms.state = UserSmsState.FAILURE;
            }
            userSmsRepository.save(sms);
        } finally {
            httpclient.close();
        }
    }

    @SuppressWarnings({"deprecation", "resource"})
    public void sendEmail(String email, String context) {
        try {
            HttpClient httpclient = new DefaultHttpClient();
            HttpPost httPost = new HttpPost(emailUrl);
            List<BasicNameValuePair> params = new ArrayList<>();
            // 您需要登录SendCloud创建API_USER，使用API_USER和API_KEY才可以进行邮件的发送。
            params.add(new BasicNameValuePair("apiUser", emailApiUser));
            params.add(new BasicNameValuePair("apiKey", emailApiKey));
            params.add(new BasicNameValuePair("from", emailName));
            params.add(new BasicNameValuePair("fromName", "我要学"));
            params.add(new BasicNameValuePair("to", email));
            params.add(new BasicNameValuePair("template_invoke_name", "test_template_active"));
            params.add(new BasicNameValuePair("subject", "我要学机构认证"));
            params.add(new BasicNameValuePair("html", context));
            httPost.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));
            logger.info("邮箱验证码：" + context);
            // 请求
            HttpResponse response = httpclient.execute(httPost);
            // 处理响应
            if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) { // 正常返回
                // 读取xml文档
                String result = EntityUtils.toString(response.getEntity());
            } else {
                logger.error("发送邮件出错");
            }
            httPost.releaseConnection();
        } catch (ParseException | IOException e) {
            logger.error("发送邮件出错", e);
        }
    }

    public void sendJpush(String number, String text, JpushTarget type, String id) {
        try {
            JPushClient jpushClient = new JPushClient(jpushSecret, jpushKey);
            PushPayload.Builder builder =
                    PushPayload.newBuilder().setPlatform(Platform.android_ios());
            IosNotification.Builder iosNotBuilder = IosNotification.newBuilder();
            AndroidNotification.Builder androidNotBuilder = AndroidNotification.newBuilder();
            Notification.Builder notBuilder = Notification.newBuilder();
            builder.setAudience(
                    Audience.newBuilder().addAudienceTarget(AudienceTarget.alias(number)).build());
            iosNotBuilder.setAlert(text);
            androidNotBuilder.setAlert(text);
            if (type != null) {
                iosNotBuilder.addExtra("type", type.toString());
                androidNotBuilder.addExtra("type", type.toString());
            }
            if (!StringUtils.isEmpty(id)) {
                if (type != null) {
                    iosNotBuilder.addExtra(type.key, id);
                    androidNotBuilder.addExtra(type.key, id);
                } else {
                    iosNotBuilder.addExtra("id", id);
                    androidNotBuilder.addExtra("id", id);
                }

            }
            notBuilder.addPlatformNotification(iosNotBuilder.build());
            notBuilder.addPlatformNotification(androidNotBuilder.build());
            if (relese) {
                builder.setOptions(Options.newBuilder().setApnsProduction(true).build());
            } else {
                builder.setOptions(Options.newBuilder().setApnsProduction(false).build());
            }
            builder.setNotification(notBuilder.build());
            jpushClient.sendPush(builder.build());
        } catch (Exception e) {
            logger.error("发送极光出错", e);
        }
    }

    public void sendSms(String phone, String msg, String ip) {
        try {
            CloseableHttpClient httpclient = HttpClients.createDefault();
            SmsBatch smsBatch = new SmsBatch();
            smsBatch.count = 1;
            smsBatch.phone = phone;
            smsBatch.msg = msg;
            smsBatch.state = UserSmsState.SUCCESS;
            smsBatch.response = UserSmsState.SUCCESS.desc;
            HttpPost httpPost = new HttpPost(smsSendUrl);
            List<NameValuePair> nvps = Lists.newArrayList();
            nvps.add(new BasicNameValuePair("apikey", smsApiKey));
            nvps.add(new BasicNameValuePair("mobile", phone));
            nvps.add(new BasicNameValuePair("text", msg));
            httpPost.setEntity(new UrlEncodedFormEntity(nvps, "UTF-8"));
            CloseableHttpResponse response = httpclient.execute(httpPost);
            try {
                String json = EntityUtils.toString(response.getEntity());
                smsBatch.response = json;
                if (json.startsWith("{\"code\":0")) {
                    smsBatch.state = UserSmsState.SUCCESS;
                } else {
                    smsBatch.state = UserSmsState.FAILURE;
                }
            } finally {
                httpclient.close();
            }
            smsBatchRepository.save(smsBatch);
        } catch (Exception e) {
        }
    }

    protected void export(String fileName, String text, HttpServletResponse response)
            throws Exception {
        String nowDate = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());
        if (StringUtils.isEmpty(fileName)) {
            fileName = nowDate;
        } else {
            fileName += "_" + nowDate;
        }
        fileName = new String(fileName.getBytes("UTF-8"), "iso-8859-1");// 为了解决中文名称乱码问题
        OutputStreamWriter osw = null;
        try {
            osw = new OutputStreamWriter(response.getOutputStream(), "UTF-8");
            // 要输出的内容
            response.setHeader("Content-Disposition", "attachment;filename=" + fileName + ".csv");
            osw.write(new String(new byte[] {(byte) 0xEF, (byte) 0xBB, (byte) 0xBF}));
            osw.write(text.replaceAll(",", "\t,").replaceAll("\n", "\t\n"));
            osw.flush();
        } catch (Exception e) {
        } finally {
            if (osw != null) {
                osw.close();
            }
        }
    }
}
